<?php

	/**
	 * @package		CoreProject
	 * @subpackage	Mime
	 *
	 * cpr_Mime_MimePart
	 * cpr_Mime_MimeParts
	 *
	 */

	class cpr_Mime_MimePart
	{
		/**
		 * @var cpr_Mime_Headers
		 */
		private $_headers = null;

		/**
		 * @var	string
		 */
		private $_charset;

		/**
		 * @var	cpr_Mime_MimeParts
		 */
		private $_subParts = null;

		/**
		 * @return	string
		 */
		private $_body;

		/**
		 * @var	cpr_Mime_GlobalCharset
		 */
		private $_global_charset;

		/**
		 * @param	cpr_Mime_GlobalCharset	&$_gc
		 * @param	string					&$rawData
		 * @return	cpr_Mime_MimePart
		 */
		public function cpr_Mime_MimePart(&$_gc, &$rawData)
		{
			$this->_global_charset =& $_gc;
			$this->_parse($rawData);
		}

		/**
		 * @return string
		 */
		public function GetBinaryBody()
		{
			switch (strtolower($this->_headers->GetHeaderValueByName(CPR_MIME_CONTENT_TRANSFER_ENCODING)))
			{
				case strtolower(CPR_MIME_QUOTED_PRINTABLE):
					return quoted_printable_decode($this->_body);
				case strtolower(CPR_MIME_BASE64):
					return base64_decode($this->_body);
				case CPR_MIME_X_UUE_L:
					return cpr_Mime_Utils::UuDecode($this->_body);
			}

			return $this->_body;
		}

		/**
		 * @return string
		 */
		public function GetDecodeTextBody()
		{
			return cpr_Core_Utils::ConvertEncoding($this->GetBinaryBody(),
				$this->_global_charset->GetMailCharset(), $this->_global_charset->GetDbCharset());
		}

		/**
		 * @return cpr_Mime_Headers
		 */
		public public function &GetHeaders()
		{
			return $this->_headers;
		}

		/**
		 * @return cpr_Mime_MimeParts
		 */
		public function &GetSubParts()
		{
			return $this->_subParts;
		}

		/**
		 * @param	string	$rawData
		 * @return	array
		 */
		private function &_mailExplode(&$rawData)
		{
			$rawData = ltrim($rawData);
			$result = array('', '');
			$headerEnding = $this->_indexOfHeadersSectionEnding($rawData);
			$result[0] = trim(substr($rawData, 0, $headerEnding));
			$body = trim(substr($rawData, $headerEnding, strlen($rawData)));
			if ($body)
			{
				$result[1] =& $body;
			}

			return $result;
		}

		
		/**
		 * @param	string	$rawData
		 * @return	int
		 */
		private function _indexOfHeadersSectionEnding(&$rawData)
		{
			$result = 0;
			$headerStartIndex = 0;
			$headerLength = 0;
			$headerEndIndex = 0;

			while (true)
			{
				$result = strpos($rawData, "\n", $headerStartIndex);
				if ($result !== false)
				{
					$headerEndIndex = $result;
					$headerLength = $headerEndIndex - $headerStartIndex;
					switch ($headerLength)
					{
						case 0:
							return $result;
							break;
						case 1:
							if ($result > 0)
							{
								if ($rawData{$result - 1} == "\r")
								{
									return $result;
								}
							}
							break;
					}
					$headerStartIndex = $result + 1;
				}
				else
				{
					return strlen($rawData) - 1;
				}
			}

			return strlen($rawData);
		}

		/**
		 * @param	strin	&$rawData
		 */
		private function _parse(&$rawData)
		{
			$parts =& $this->_mailExplode($rawData);
			unset($rawData);

			$this->_headers = new cpr_Mime_Headers($this->_global_charset, $parts[0]);

			/* charset parsing */
			$contentTypeHeader =& $this->_headers->GetHeaderByName(CPR_MIME_CONTENT_TYPE);
			if ($contentTypeHeader != null)
			{
				$headerParameters = new cpr_Mime_HeaderParameters($this->_global_charset, $contentTypeHeader->Value());
				$param =& $headerParameters->GetByName(CPR_MIME_CHARSET_L);
				if (null !== $param)
				{
					$this->_global_charset->SetMailCharset($param->Value());
				}
			}

			$this->_charset = $this->_global_charset->GetMailCharset();

			if (count($parts) == 2)
			{
				$bound = $this->_headers->GetBoundary();
				if (strlen($bound) > 1)
				{
					$mimePos = strpos($parts[1], '--'.$bound);
					$this->_body = substr($parts[1], 0, $mimePos);
					$parts[1] = explode('--'.$bound, substr($parts[1], $mimePos));

					if (count($parts[1]) >= 2)
					{
						$this->_subParts = new cpr_Mime_MimeParts($this->_global_charset, $this);
						for ($i = 1, $c = count($parts[1]); $i < $c; $i++)
						{
							if (trim($parts[1][$i]) == '--' || !$parts[1][$i])
							{
								continue;
							}
							$this->_subParts->Add(new cpr_Mime_MimePart($this->_global_charset, $parts[1][$i]));
						}
					}
				}
				else
				{
					$this->_body =& $parts[1];
				}
			}
		}

		/**
		 * @return string
		 */
		public function ToString($withoutBcc = false)
		{
			$retval = $this->_headers->ToString($withoutBcc).CPR_CRLF;
			$retval .= $this->_body;
			if (null !== $this->_subParts && $this->_subParts->Count() > 0)
			{
				$retval .= $this->_subParts->ToString();
			}
			return $retval.CPR_CRLF;
		}
	}

	class cpr_Mime_MimeParts extends cpr_Core_Collection
	{
		/**
		 * @var cpr_Mime_MimePart
		 */
		private $_parent;

		/**
		 * @var	cpr_Mime_GlobalCharset
		 */
		private $_global_charset;

		/**
		 * @param	cpr_Mime_GlobalCharset	&$_gc
		 * @param	cpr_Mime_MimePart		&$_parent
		 */
		function cpr_Mime_MimeParts(&$_gc, &$_parent)
		{
			$this->_global_charset =& $_gc;
			$this->_parent =& $_parent;
		}

		/**
		 * @return string
		 */
		function ToString()
		{
			$retval = '';
			$lineStr = '--';
			if ($this->Count() > 0)
			{
				$bound = $this->_parent->GetBoundary();
				for ($i = 0, $c = $this->Count(); $i < $c; $i++)
				{
					$mimePart =& $this->Get($i);
					$retval .= $lineStr.$bound.CPR_CRLF;
					$retval .= $mimePart->ToString().CPR_CRLF;
					unset ($mimePart);
				}
				$retval .= $lineStr.$bound.$lineStr.CPR_CRLF;
			}

			return $retval;
		}

	}

